﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace OAuth.Verifiers
{
    /// <summary>
    /// does section 4.1 verification on the url parameters
    /// </summary>
    static class ServiceProviderUriVerifier
    {
        /// <summary>
        /// 
        /// </summary>
        /// <remarks>
        /// For guidelines regarding the creation of new exception types, see
        ///    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconerrorraisinghandlingguidelines.asp
        /// and
        ///    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp    
        /// </remarks>
        [global::System.Serializable]
        public sealed class BadServiceProviderUriException : OAuth.Verifiers.ServiceProviderVerifier.BadServiceProviderException
        {
            #region public BadServiceProviderUriException()

            /// <summary>
            /// Initializes a new instance of the <see cref="T:BadServiceProviderUriException"/> class
            /// </summary>
            public BadServiceProviderUriException()
            {
            }

            #endregion

            #region public BadServiceProviderUriException(string message) : base(message)

            /// <summary>
            /// Initializes a new instance of the <see cref="T:BadServiceProviderUriException"/> class
            /// </summary>
            /// <param name="message">A <see cref="T:System.String"/> that describes the error. The content of message is intended to be understood by humans. The caller of this constructor is required to ensure that this string has been localized for the current system culture.</param>
            public BadServiceProviderUriException(string message)
                : base(message)
            {
            }

            #endregion

            #region public BadServiceProviderUriException(string message, Exception inner) : base(message, inner)

            /// <summary>
            /// Initializes a new instance of the <see cref="T:BadServiceProviderUriException"/> class
            /// </summary>
            /// <param name="message">A <see cref="T:System.String"/> that describes the error. The content of message is intended to be understood by humans. The caller of this constructor is required to ensure that this string has been localized for the current system culture.</param>
            /// <param name="inner">The exception that is the cause of the current exception. If the innerException parameter is not a null reference, the current exception is raised in a catch block that handles the inner exception.</param>
            public BadServiceProviderUriException(string message, Exception inner)
                : base(message, inner)
            {
            }

            #endregion
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pUri"></param>
        /// <exception cref="BadServiceProviderUriException">If the Uri fails verification</exception>
        public static void VerifyUserAuthorizationUrl(Uri pUri)
        {
            VerifyUri(pUri);
            foreach (var param in Utilities.ParseParameters(pUri.Query))
                if (param.Key.ToUpper().StartsWith("OAUTH_"))
                    throw new BadServiceProviderUriException("The Authorization Url query may not contain parameters starting with 'oauth_'");
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pUri"></param>
        /// <exception cref="BadServiceProviderUriException">If the Uri fails verification</exception>
        public static void VerifyRequestTokenUri(Uri pUri)
        {
            VerifyUri(pUri);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pUri"></param>
        /// <exception cref="BadServiceProviderUriException">If the Uri fails verification</exception>
        public static void VerifyAccessTokenUri(Uri pUri)
        {
            VerifyUri(pUri);
        }

        private static void VerifyUri(Uri pUri)
        {
            if (pUri == null) 
            {
                throw new BadServiceProviderUriException("Uri may not be null");
            }

            if (string.IsNullOrEmpty(pUri.Scheme))
            {
                throw new BadServiceProviderUriException("Uri MUST contain scheme");
            }

            if (string.IsNullOrEmpty(pUri.Authority))
            {
                throw new BadServiceProviderUriException("Uri MUST contain authority");
            }

            if (string.IsNullOrEmpty(pUri.AbsolutePath))
            {
                throw new BadServiceProviderUriException("Uri MUST contain Path and MAY contain Query");
            }
        }
    }
}
